#ifndef ___BASE_OBJECT_H
#define ___BASE_OBJECT_H
#define  _CRT_SECURE_NO_WARNINGS
#include "interface.h"

class Candidate:public ICandidate
{
public:
	virtual int getValue() const ;//获取候选数的状态标记
	virtual int setValue(int val);//设置候选数的状态标记
	virtual const char* toString() ;
public:
	Candidate(int nv):nVal(nv),nTag(STA_NORMAL)	
	{
		memset(pszName,0,sizeof(pszName));
    }
private:
	int nVal;
	int nTag;
	char pszName[20];
};


class Cell:public ICell
{
public:
	virtual int registerCellSet(ICellSet *);//关联CellSet
	virtual Number getNumber() const ; //获取当前数值，只返回确切的数字（0-9）
    virtual Point getPoint() ; //获取当前坐标值
    virtual Number setNumber(Number num);//设置数值，不做其他影响
    virtual int setCandidate(Number num,int tag);//设置该数个的某个候选数的状态
    virtual int getCandidate(Number num); //试图获取数格某个候选数的状态
    virtual ICandidates getCandidates();//获取候选数列表
    virtual ICellSets getCellSets();//获取关联的CellSet
    virtual ICellSet *getCellSet(int nType);//获取指定类型的关联数格集合
    virtual void connect(ICell *); //与其他数格建立连接
    virtual ICells getConnectedCells(); //获取关联的CellSet里的数格集合
    virtual const char* toString();
public:
    Cell(const Point &p):nVal(0),pt(p)
	{
		try
		{
			memset(pszName,0,sizeof(pszName));
            for(int i=LOWER_BOUNDER-1;i<UPPER_BOUNDER;++i)
			{
				ICandidate *pCand=new Candidate(i+1);
				candidates.push_back(pCand);
			}
		}
		catch   (const   exception   &e)  
		{  
			cout   <<   e.what()   <<   endl;  
		}
		catch(...)
		{
			cerr<<"Exception on Cell::ctor() on " << __FILE__ << " Line:" <<__LINE__<<endl;
		}
	}
	~Cell()
    {
        for(int i=LOWER_BOUNDER-1;i<UPPER_BOUNDER;++i)
		{
			delete candidates[i];
		}
	}
private:
	int nVal;
	char pszName[50];
    ICellSets cellsets;
    ICandidates candidates;
    ICells cells;//通过cellsets关联的其他数格（去重复）
	Point pt;
};


//CellSet应该也有命名
class CellSet:public ICellSet
{
public:
	virtual bool registerCell(ICell *); //注册此条CellSet关注的数格
    virtual ICells getCells();  //获取相关的数格列表 （vector复制是否会带来较大的消耗？）
    virtual int getType();      //获取数格集合对象的类型，类型会影响解题的算法过程
	virtual const char* toString() ;
	CellSet(CellSet_TYPE type,int csid):nType(type),nId(csid)
	{
		memset(pszName,0,sizeof(pszName));
	}
	static int xy2z(const Point &p)
	{
		return (p.getX()-1)/3 +1 + ((p.getY()-1)/3 ) * 3 ;
	}
private:
	int nType;
	int nId;
	char pszName[50];
    ICells  cells;
};

class Puzzle:public IPuzzle
{
public:
	virtual int loadPuzzle(const char *pszSudoku);
    virtual const char* exportPuzzle(int nType=FormatNumber81);
        virtual ICell *getCell(const Point &);
        virtual ICells getCells();//取出全部的数个对象
        virtual ICellSets getCellSets(int); //根据传入类型，获取数格集合
        virtual Number getNumber(const Point &);//获取数值
        virtual Number setNumber(const Point &,Number num);//设置数值，不影响其他数格的候选数
        virtual Number unsetNumber(const Point &,Number num);//取消数值设置，不影响其他数格的候选数

	//自动解题主要的接口
        virtual Number chainSetNumber(const Point &,Number num); //设置数值，并且触发链式反应，将其他数格的候选数抹去
	
        virtual Number chainUnsetNumber(const Point &,Number num);//取消设置数值，并且触发链式反应，将其他数格的候选数填回去
        virtual int setCandidate(const Point &,Number num,int tag);//设置候选数，不影响其他数格
        virtual bool hasCandidate(const Point &,Number);//检查某数格是否设置了某候选数
		virtual bool chkNumber(const Point &,Number);//检查某数格是否可以填某数（在可见数格里不冲突）
		virtual int getStatus();//返回数独题的状态：未完成但有效0，完成且有效1，存在错误2

	Puzzle();
    ~Puzzle();

	void clear();

private:
    ICells cells;
    ICellSets col_cellsets;
    ICellSets row_cellsets;
    ICellSets box_cellsets;

    char pszPuzzle[10000];
    char pszOrigin[10000];
};



class SudokuPuzzleFactory:public IObject //根据游戏类型产生不同的SudokuFactory
{
	IPuzzle *createPuzzle(int sudoku_type)
	{
		switch(sudoku_type)
		{
		case STANDARD_SUDOKU:
		default:
			return new Puzzle();//标准数独游戏
		}
	}
};


class Solver:public ISolver
{
public:
    virtual int doSolve(IPuzzle *,Operations &) ; //开始解题并返回解题过程（参数列表里）
    virtual int doStep(IPuzzle *,Operations &,int step=1) ;//对传入的Puzzle进行若干步解题操作，并返回解题过程（参数列表里），函数返回０表示成功，否则有错误
    virtual Operations getTips(IPuzzle *,int nStep=1);//获取一个提示，但是不进行解题操作，nStep为最多只需要的提示数，只是一个建议值
	virtual int registerHelper(IHelper *)  ;//注册解题接口，顺序相关
private:
    vector<IHelper *> helpers; //解题技巧列表
};



#endif
